﻿namespace SaxParser
{
    using System;
    using System.Collections.Generic;
    using System.Xml;

    /// <summary>
    /// My Sax Parser
    /// </summary>
    public class MySaxParser
    {
        #region Main Logic

        public void Parse(string path)
        {
            try
            {
                XmlTextReader reader = new XmlTextReader(path);

                while (reader.Read())
                {
                    switch (reader.NodeType)
                    {
                        case XmlNodeType.Element:
                            {
                                List<KeyValuePair<string, string>> attributes = new List<KeyValuePair<string, string>>();
                                string tagName = reader.Name;

                                if (reader.HasAttributes)
                                {
                                    for (int i = 0; i < reader.AttributeCount; i++)
                                    {
                                        reader.MoveToAttribute(i);
                                        attributes.Add(new KeyValuePair<string, string>(reader.Name, reader.Value));
                                    }
                                }

                                if (OnElementStart != null)
                                    OnElementStart(this, new ElementStartEventArgs(tagName, attributes));

                                break;
                            }
                        case XmlNodeType.Text:
                            {
                                if (OnText != null)
                                    OnText(this, new MyEventArgs("Tag value:", reader.Value));

                                break;
                            }
                        case XmlNodeType.EndElement:
                            {
                                if (OnElementEnd != null)
                                    OnElementEnd(this, new MyEventArgs("End of tag. Name:", reader.Name));

                                break;
                            }
                        case XmlNodeType.XmlDeclaration:
                            {
                                if (OnDocumentDeclaration != null)
                                    OnDocumentDeclaration(this, new MyEventArgs("Find document declaration:", reader.Value));

                                break;
                            }
                        case XmlNodeType.DocumentType:
                            {
                                if (OnDocumentType != null)
                                    OnDocumentType(this, new MyEventArgs("Document type:", reader.Value));

                                break;
                            }
                        case XmlNodeType.Comment:
                            {
                                if (OnComment != null)
                                    OnComment(this, new MyEventArgs("Find comment. Value:", reader.Value));

                                break;
                            }

                        default:
                            {
                                break;
                            }
                    }
                }
            }
            catch (XmlException e)
            {
                if (OnError != null)
                    OnError(this, new MyEventArgs("Invalid input xml document. Error:", e.Message));
            }
            catch (Exception exp)
            {
                if (OnError != null)
                    OnError(this, new MyEventArgs("Error:", exp.Message));
            }
        }

        #endregion

        #region Delegates

        public delegate void ElenemtStartEventHandler(object sender, ElementStartEventArgs e);
        public delegate void ElenemtEndEventHandler(object sender, MyEventArgs e);
        public delegate void TextEventHandler(object sender, MyEventArgs e);
        public delegate void DocumentDeclarationEventHandler(object sender, MyEventArgs e);
        public delegate void DocumentTypeEventHandler(object sender, MyEventArgs e);
        public delegate void CommentEventHandler(object sender, MyEventArgs e);
        public delegate void ErrorEventHandler(object sender, MyEventArgs e);

        #endregion

        #region Events

        public event ElenemtEndEventHandler OnElementEnd;
        public event ElenemtStartEventHandler OnElementStart;
        public event TextEventHandler OnText;
        public event DocumentDeclarationEventHandler OnDocumentDeclaration;
        public event DocumentTypeEventHandler OnDocumentType;
        public event CommentEventHandler OnComment;
        public event ErrorEventHandler OnError;

        #endregion
    }
}
